#include "http_server.h"
#include <sstream>
#include <fstream>
#include <iostream>

namespace example {

HttpServer::HttpServer(int port, int timeout) : _server(port) 
{
    _server.enableInactiveRelease(timeout);
    _server.setClosedCallback(std::bind(&HttpServer::onClosed, this, std::placeholders::_1));
    _server.setConnectedCallback(std::bind(&HttpServer::onConnected, this, std::placeholders::_1));
    _server.setMessageCallback(std::bind(&HttpServer::onMessage, this, std::placeholders::_1, std::placeholders::_2));
    // _mysqlManager = std::make_shared<util::MySQLManager>("localhost", "root", "password", "calculator_db");
}

void HttpServer::errorHandler(const http::HttpRequest& req, http::HttpResponse* rsp) 
{
    std::string errorPath = _basedir + "/error/" + std::to_string(rsp->_statu) + ".html";
    
    // 若对应错误页面不存在，使用默认硬编码页面
    if (!http::HttpUtil::isRegular(errorPath)) 
    {
        std::string body = "<html><body><h1>" + std::to_string(rsp->_statu) + " " + http::HttpUtil::statuDesc(rsp->_statu) + "</h1></body></html>";
        rsp->setContent(body, "text/html");
        return;
    }
    
    // 读取错误页面文件
    std::string body;
    http::HttpUtil::readFile(errorPath, &body);
    rsp->setContent(body, "text/html");
}

void HttpServer::writeReponse(const net::PtrConnection& conn, const http::HttpRequest& req, http::HttpResponse& rsp) 
{
    if (!conn || !conn->connected()) 
    {
        LOG_ERROR("Connection is not valid, cannot write response");
        return;
    }
    // 完善响应头部
    if (req.close() == true) 
    {
        rsp.setHeader("Connection", "close");
    } 
    else 
    {
        rsp.setHeader("Connection", "keep-alive");
    }
    
    if (!rsp._body.empty() && !rsp.hasHeader("Content-Length")) 
    {
        rsp.setHeader("Content-Length", std::to_string(rsp._body.size()));
    }
    
    if (!rsp._body.empty() && !rsp.hasHeader("Content-Type")) 
    {
        rsp.setHeader("Content-Type", "application/octet-stream");
    }
    
    if (rsp._redirectFlag == true) 
    {
        rsp.setHeader("Location", rsp._redirectUrl);
    }
    
    // 组织HTTP响应
    std::stringstream rspStr;
    rspStr << req._version << " " << std::to_string(rsp._statu) << " " << http::HttpUtil::statuDesc(rsp._statu) << "\r\n";
    
    for (const auto& head : rsp._headers) {
        rspStr << head.first << ": " << head.second << "\r\n";
    }
    
    rspStr << "\r\n";
    rspStr << rsp._body;
    
    // 发送响应
    conn->send(rspStr.str().c_str(), rspStr.str().size());
}

bool HttpServer::isFileHandler(const http::HttpRequest& req) const 
{
    // 检查是否设置了静态资源根目录
    if (_basedir.empty()) 
    {
        return false;
    }
    
    // 检查请求方法
    if (req._method != "GET" && req._method != "HEAD") 
    {
        return false;
    }
    
    // 检查请求路径合法性
    if (!http::HttpUtil::validPath(req._path)) 
    {
        return false;
    }
    
    // 构建完整路径
    std::string reqPath = _basedir + req._path;
    if (req._path.back() == '/')
    {
        reqPath += "index.html";
    }
    
    // 检查文件是否存在且为普通文件
    return http::HttpUtil::isRegular(reqPath);
}

void HttpServer::fileHandler(const http::HttpRequest& req, http::HttpResponse* rsp) 
{
    // 构建完整路径
    std::string reqPath = _basedir + req._path;
    if (req._path.back() == '/') 
    {
        reqPath += "index.html";
    }
    
    // 读取文件内容
    bool ret = http::HttpUtil::readFile(reqPath, &rsp->_body);
    if (!ret) 
    {
        rsp->_statu = 404;
        return;
    }
    
    // 设置Content-Type
    std::string mime = http::HttpUtil::extMime(reqPath);
    rsp->setHeader("Content-Type", mime);
}

void HttpServer::dispatcher(http::HttpRequest& req, http::HttpResponse* rsp, Handlers& handlers) 
{
    // 遍历路由表，查找匹配的处理函数
    for (auto& handler : handlers) 
    {
        const std::regex& re = handler.first;
        const Handler& functor = handler.second;
        
        if (std::regex_match(req._path, req._matches, re)) 
        {
            return functor(req, rsp); // 执行处理函数
        }
    }
    
    // 未找到匹配的路由
    rsp->_statu = 404;
}

void HttpServer::route(http::HttpRequest& req, http::HttpResponse* rsp) 
{
    // 处理静态资源请求
    if (isFileHandler(req)) 
    {
        return fileHandler(req, rsp);
    }
    
    // 处理功能性请求
    if (req._method == "GET" || req._method == "HEAD") 
    {
        return dispatcher(req, rsp, _getRoute);
    } 
    else if (req._method == "POST") 
    {
        return dispatcher(req, rsp, _postRoute);
    } 
    else if (req._method == "PUT") 
    {
        return dispatcher(req, rsp, _putRoute);
    } 
    else if (req._method == "DELETE") 
    {
        return dispatcher(req, rsp, _deleteRoute);
    }
    
    // 不支持的请求方法
    rsp->_statu = 405; // Method Not Allowed
}

void HttpServer::onConnected(const net::PtrConnection& conn) 
{
    LOG_INFO("NEW CONNECTION %p", conn.get());
    conn->setContext(http::HttpContext());
}

void HttpServer::onClosed(const net::PtrConnection& conn) 
{
    LOG_INFO("CLOSE CONNECTION:%p", conn.get());
}

void HttpServer::onMessage(const net::PtrConnection& conn, net::Buffer* buffer) 
{
    while (buffer->readAbleSize() > 0) 
    {
        // 获取上下文
        http::HttpContext* context = conn->getContext()->get<http::HttpContext>();
        if (!context) {
            LOG_ERROR("Context is null!");  // 添加空指针检查
            return;
        }
        
        // 解析HTTP请求
        context->recvHttpRequest(buffer);
        http::HttpRequest& req = context->request();
        http::HttpResponse rsp(context->respStatu());
        
        // 处理解析错误
        if (context->respStatu() >= 400) 
        {
            errorHandler(req, &rsp);
            writeReponse(conn, req, rsp);
            context->reSet();
            buffer->moveReadOffset(buffer->readAbleSize());
            conn->shutdown();
            return;
        }
        
        // 检查请求是否完整
        if (context->recvStatu() != RECV_HTTP_OVER) 
        {
            return; // 等待更多数据
        }
        
        // 路由分发
        route(req, &rsp);
        
        // 发送响应
        writeReponse(conn, req, rsp);
        
        // 重置上下文
        context->reSet();
        
        // 根据连接类型决定是否关闭连接
        if (rsp.close()) 
        {
            conn->shutdown();
        }
    }
}

} // namespace example